﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Printing;
using System.Collections.Generic;
using PrintScreens.Service.Printing;
using DataModel;
using System.Threading;
namespace PrintScreens
{
    class PrintHelper
    {
        PrintDocument PD = new PrintDocument();
        IPrintWatcher PW;
        public PrintHelper(IPrintWatcher PW)
        {
            this.PW = PW;
            PrintStatusUpdate();
            //Must initialize service from correct thread.
            SRV.ToString();
            PD.BeginPrint += new EventHandler<BeginPrintEventArgs>(PD_BeginPrint);
            PD.PrintPage += new EventHandler<PrintPageEventArgs>(PD_PrintPage);
            PD.EndPrint += new EventHandler<EndPrintEventArgs>(PD_EndPrint);
        }
        public void GotFirstPage(PrintingServiceFirstPage FP)
        {
            Pages.Enqueue(new SilverlightControl1(FP));
            //((ResultWaiter<UIElement>)e.UserState).Value = new SilverlightControl1(e.Result);
            CurrentPage++;
            PrintStatusUpdate();
            //Pages.Enqueue(FirstPage);
            Prepare();
        }



        public void BeginPrinting()
        {
            PD.Print("SSCC Renewal Documents");
        }

        void Prepare()
        {
            SRV.LoadNumberOfPagesCompleted += new EventHandler<LoadNumberOfPagesCompletedEventArgs>(SRV_LoadNumberOfPagesCompleted);
            SRV.LoadFirstPageCompleted += new EventHandler<LoadFirstPageCompletedEventArgs>(SRV_LoadFirstPageCompleted);
            SRV.LoadAdditionalPageCompleted +=new EventHandler<LoadAdditionalPageCompletedEventArgs>(SRV_LoadAdditionalPageCompleted);
            SRV.LoadParentalConsentCompleted += new EventHandler<LoadParentalConsentCompletedEventArgs>(SRV_LoadParentalConsentCompleted);
            SRV.LoadNumberOfPagesAsync();
        }

        int CurrentPage = 0;
        int? NumberOfPages = null;
        bool Done = false;


        void SRV_LoadNumberOfPagesCompleted(object sender, LoadNumberOfPagesCompletedEventArgs e)
        {
            NumberOfPages = (1 + e.Result.NumberOfAdditionalPages + e.Result.NumberOfParentalConsentForms);
            PrintStatusUpdate();
            for (int i = 0; i < e.Result.NumberOfAdditionalPages; i++)
            {
                //var AP = new ResultWaiter<UIElement>();
                //Pages.Enqueue(AP);
                int a = i;
                DownloadPage.Enqueue(() => SRV.LoadAdditionalPageAsync(a));
            }
            for (int i = 0; i < e.Result.NumberOfParentalConsentForms; i++)
            {
                //var AP = new ResultWaiter<UIElement>();
                //Pages.Enqueue(AP);
                int v = i;
                DownloadPage.Enqueue(() => SRV.LoadParentalConsentAsync(v));
            }
            //SRV.LoadFirstPageAsync();
            DownloadPage.Enqueue(() =>
            {
                PW.Ready();
            });
            DownloadPage.Dequeue()();
        }

        void SRV_LoadFirstPageCompleted(object sender, LoadFirstPageCompletedEventArgs e)
        {
            Pages.Enqueue(new SilverlightControl1(e.Result));
            //((ResultWaiter<UIElement>)e.UserState).Value = new SilverlightControl1(e.Result);
            CurrentPage++;
            PrintStatusUpdate();

            DownloadPage.Dequeue()();
        }
        void SRV_LoadAdditionalPageCompleted(object sender, LoadAdditionalPageCompletedEventArgs e)
        {
            Pages.Enqueue(new AditionalPageForLegalStatements(e.Result));
            //((ResultWaiter<UIElement>)e.UserState).Value = new UserControl();

            CurrentPage++;
            PrintStatusUpdate();

            DownloadPage.Dequeue()();
        }
        void SRV_LoadParentalConsentCompleted(object sender, LoadParentalConsentCompletedEventArgs e)
        {
            Pages.Enqueue(new ParentalConsentForm(e.Result));
            //((ResultWaiter<UIElement>)e.UserState).Value = new UserControl();

            CurrentPage++;
            PrintStatusUpdate();

            DownloadPage.Dequeue()();
        }


        Queue<Action> DownloadPage = new Queue<Action>();
        Queue<UIElement> Pages = new Queue<UIElement>();

        void PD_BeginPrint(object sender, BeginPrintEventArgs e)
        {
            PrintStatusUpdate();
        }
        void PD_PrintPage(object sender, PrintPageEventArgs e)
        {
            e.PageVisual = Pages.Dequeue();
            e.HasMorePages = (Pages.Count != 0);
        }
        void PD_EndPrint(object sender, EndPrintEventArgs e)
        {
            Done = true;
            PrintStatusUpdate();
        }

        PrintingServiceClient SRV = ServiceConfig.NewPrintingClient();

        void PrintStatusUpdate()
        {
            string NewStatus = "";
            if (Done)
            {
                NewStatus = "Printing Finished";
                PW.Done();
            }
            else if (NumberOfPages.HasValue)
            {
                NewStatus = String.Format("Loading Page {0} of {1}", CurrentPage, NumberOfPages);
            }
            else
            {
                NewStatus = "Loading Data";
            }
            PW.PrintStatusUpdate(NewStatus);
        }
    }
    interface IPrintWatcher
    {
        void PrintStatusUpdate(string Status);
        void Done();
        void Ready();
    }

    class ResultWaiter<T>
    {
        T V;
        ManualResetEvent MRE = new ManualResetEvent(false);
        public T Value 
        { 
            get
            {
                MRE.WaitOne();
                return V;
            }
            set
            {
                V = value;
                MRE.Set();
            }
        }

        public static implicit operator Func<T>(ResultWaiter<T> R)
        {
            return new Func<T>(() => R.Value);
        }
    }
}
